package com.zeratul.common.mybatis.config;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.zeratul.common.core.factory.YmlPropertySourceFactory;
import com.zeratul.common.mybatis.core.page.aop.PageAop;
import com.zeratul.common.mybatis.core.page.aop.WebPageAop;
import com.zeratul.common.mybatis.core.page.plugin.PagePlugin;
import com.zeratul.common.mybatis.core.page.prop.ZtPageConfiguration;
import com.zeratul.common.mybatis.core.sqlexec.interceptor.SqlLogInterceptor;
import com.zeratul.common.mybatis.core.sqlexec.plugin.SQLExecPlugin;
import com.zeratul.common.mybatis.core.sqlexec.prop.ZtExecSqlConfiguration;
import com.zeratul.common.mybatis.handler.InjectionMetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Slf4j
@AutoConfiguration
@MapperScan(basePackages = {"com.zeratul.**.mapper", "com.zeratul.**.dao"})
@PropertySource(value = "classpath:common-mybatis.yml", factory = YmlPropertySourceFactory.class)
@Import({ZtPageConfiguration.class, ZtExecSqlConfiguration.class})
@EnableAspectJAutoProxy
@EnableTransactionManagement(proxyTargetClass = true)
public class MybatisAutoConfiguration {

    /**
     * 装配Mybatis SQL执行记录插件
     */
    @Bean
    //有mybatis的环境
    @ConditionalOnClass(SqlSessionFactory.class)
    //指定属性值为true时才能加载
    @ConditionalOnProperty(prefix = "zt-plugin.execsql", value = "enable", havingValue = "true", matchIfMissing = true)
    public SQLExecPlugin getExecSqlPlugin(){
        log.debug("【Mybatis插件】SQL记录插件加载....");
        return new SQLExecPlugin();
    }

    /**
     * 装配Mybatis SQL日志拦截器
     */
    @Bean
    @ConditionalOnBean(SQLExecPlugin.class)
    //web环境才能加载
    @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
    //指定属性值为true时才能加载
    @ConditionalOnProperty(prefix = "zt-plugin.execsql", value = "enable", havingValue = "true", matchIfMissing = true)
    public SqlLogInterceptor getSqlLogInterceptor() {
        return new SqlLogInterceptor();
    }

    /**
     * 装配Mybatis 分页插件
     */
    @Bean
    //有mybatis的环境
    @ConditionalOnClass(SqlSessionFactory.class)
    //指定属性值为true时才能加载
    @ConditionalOnProperty(prefix = "zt-plugin.page", value = "enable", havingValue = "true", matchIfMissing = true)
    public PagePlugin getPagePlugin(){
        log.debug("【Mybatis插件】分页插件加载....");
        return new PagePlugin();
    }

    /**
     * 装配aop
     */
    @Bean
    //指定属性值为true时才能加载
    @ConditionalOnProperty(prefix = "zt-plugin.page", value = "enable", havingValue = "true", matchIfMissing = true)
    public PageAop getPageAop(){
        return new PageAop();
    }

    /**
     * 装配aop
     */
    @Bean
    //存在aop环境
    //当存在分页插件时，才会加载该AOP
    @ConditionalOnBean(PagePlugin.class)
    //web环境才能加载
    @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
    //指定属性值为true时才能加载，缺省不加载
    @ConditionalOnProperty(prefix = "zt-plugin.page", value = "web-handler", havingValue = "true", matchIfMissing = false)
    public WebPageAop getWebPageAop(){
        return new WebPageAop();
    }

    /**
     * 元对象字段填充控制器
     */
    @Bean
    public MetaObjectHandler metaObjectHandler() {
        return new InjectionMetaObjectHandler();
    }
}
